package com.bestcem.xm.member.grpc.service;

import cn.hutool.core.collection.CollectionUtil;
import com.bestcem.bp.grpc.v1.base.BaseTime;
import com.bestcem.xm.common.core.domain.web.RpcStatusResult;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.GRpcUtil;
import com.bestcem.xm.member.grpc.service.param.PageParam;
import com.bestcem.xm.member.grpc.service.param.SortParam;
import com.bestcem.xm.member.grpc.service.param.imports.*;
import com.bestcem.xm.member.grpc.v1.common.Sort;
import com.bestcem.xm.member.grpc.v1.services.*;
import com.bestcem.xm.member.service.ImportService;
import com.bestcem.xm.member.service.dto.ImportRecordDTO;
import com.bestcem.xm.member.service.dto.ImportRecordDetailDTO;
import com.bestcem.xm.member.service.dto.PageDTO;
import com.bestcem.xm.member.service.param.ImportProjectParam;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 导入 相关grpc服务
 *
 * @author yf.wang <yf.wang@idiaoyan.com>
 * @version V1.0
 * @date 2021/7/20
 */
@GrpcService
public class ImportGrpcService extends ImportServiceGrpc.ImportServiceImplBase {

    @Resource
    private ImportService importService;

    /**
     * 模板下载
     *
     * @param request
     * @param responseObserver
     */
    @Override
    public void downLoadTemplate(DownLoadTemplateRequest request, StreamObserver<DownLoadTemplateResponse> responseObserver) {
        DownLoadTemplateResponse.Builder builder = DownLoadTemplateResponse.newBuilder();

        // 组装参数
        DownLoadTemplateParam param = requestToDownLoadTemplateParam(request);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        // 下载模板
        ServiceResult<String> result = importService.downLoadTemplate(param);
        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success());
            builder.setFileUrl(result.getData());
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * 检查是否有正在导入的任务
     *
     * @param request
     * @param responseObserver
     */
    @Override
    public void checkImport(CheckImportRequest request, StreamObserver<CheckImportResponse> responseObserver) {
        CheckImportResponse.Builder builder = CheckImportResponse.newBuilder();

        // 组装参数
        CheckImportParam param = requestToCheckImportParam(request);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        // 获取导入进度
        ServiceResult<String> result = importService.checkImport(param);
        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success());
            builder.setId(result.getData());
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * 获取导入列表
     *
     * @param request
     * @param responseObserver
     */
    @Override
    public void listImportRecords(ListImportRecordsRequest request, StreamObserver<ListImportRecordsResponse> responseObserver) {
        ListImportRecordsResponse.Builder builder = ListImportRecordsResponse.newBuilder();

        // 组装参数
        ListImportRecordsParam param = requestToListImportRecordsParam(request);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        // 获取导入列表
        ServiceResult<PageDTO> result = importService.listImportRecords(param);
        if (result.isSuccess()) {
            PageDTO data = result.getData();
            builder.setStatus(RpcStatusResult.success());
            builder.setTotal(data.getTotal().intValue());
            builder.addAllRecords(dataToRecords(data.getRows()));
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * 获取导入进度
     *
     * @param request
     * @param responseObserver
     */
    @Override
    public void getImportProgress(GetImportProgressRequest request, StreamObserver<GetImportProgressResponse> responseObserver) {
        GetImportProgressResponse.Builder builder = GetImportProgressResponse.newBuilder();

        // 组装参数
        GetImportProgressParam param = requestToGetImportProgressParam(request);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        // 获取导入进度
        ServiceResult<Float> result = importService.getImportProgress(param);
        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success());
            builder.setProgress(result.getData());
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * 导入失败列表
     *
     * @param request
     * @param responseObserver
     */
    @Override
    public void listImportDetails(ListImportDetailsRequest request, StreamObserver<ListImportDetailsResponse> responseObserver) {
        ListImportDetailsResponse.Builder builder = ListImportDetailsResponse.newBuilder();

        // 组装参数
        ListImportDetailsParam param = requestToListImportDetailsParam(request);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        // 获取导入进度
        ServiceResult<PageDTO> result = importService.listImportDetails(param);
        if (result.isSuccess()) {
            PageDTO data = result.getData();
            builder.setStatus(RpcStatusResult.success());
            builder.setTotal(data.getTotal().intValue());
            builder.addAllDetails(dataToImportFailureDetail(data.getRows()));
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * 获取单个导入记录
     *
     * @param request
     * @param responseObserver
     */
    @Override
    public void getImportRecord(GetImportRecordRequest request, StreamObserver<GetImportRecordResponse> responseObserver) {
        GetImportRecordResponse.Builder builder = GetImportRecordResponse.newBuilder();

        // 组装参数
        GetImportRecordParam param = requestToGetImportRecordParam(request);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        // 获取导入进度
        ServiceResult<ImportRecordDTO> result = importService.getImportRecord(param);
        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success());
            builder.setRecord(importRecordDTOToImport(result.getData()));
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * 导入联系人
     *
     * @param request
     * @param responseObserver
     */
    @Override
    public void importMembers(ImportMembersRequest request, StreamObserver<ImportMembersResponse> responseObserver) {
        ImportMembersResponse.Builder builder = ImportMembersResponse.newBuilder();

        // 组装参数
        ImportMembersParam param = requestToImportMembersParam(request);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        // 导入联系人
        ServiceResult<String> result = importService.importMembers(param);
        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success());
            builder.setId(result.getData());
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * 项目导入
     *
     * @param request
     * @param responseObserver
     */
    @Override
    public void importProjects(ImportProjectsRequest request, StreamObserver<ImportProjectsResponse> responseObserver) {
        ImportProjectsResponse.Builder builder = ImportProjectsResponse.newBuilder();

        // 组装参数
        ImportProjectsParam param = requestToImportProjectsParam(request);

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(param);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ImportProjectParam importProjectParam = new ImportProjectParam();
        importProjectParam.setExistedUpdate(param.getExistedUpdate());
        importProjectParam.setNullUpdate(param.getNullUpdate());
        importProjectParam.setOrgId(param.getOrgId());
        importProjectParam.setUserId(param.getUserId());
        importProjectParam.setFileUrl(param.getFileUrl());
        importProjectParam.setImportType(param.getImportType());

        // 导入项目
        ServiceResult<String> result = importService.importProjects(importProjectParam);
        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success());
            builder.setId(result.getData());
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }



    /**
     * request to ImportProjectsParam
     *
     * @param request
     * @return
     */
    private ImportProjectsParam requestToImportProjectsParam(ImportProjectsRequest request) {
        ImportProjectsParam param = new ImportProjectsParam();
        param.setOrgId(request.getOrgId());
        param.setUserId(request.getUserId());
        param.setAttribute(request.getMemberTypeValue());
        param.setImportType(request.getImportTypeValue());
        param.setExistedUpdate(request.getExistedUpdate());
        param.setNullUpdate(request.getNullUpdate());
        param.setFileUrl(request.getFileUrl());
        return param;
    }

    /**
     * request to ImportMembersParam
     *
     * @param request
     * @return
     */
    private ImportMembersParam requestToImportMembersParam(ImportMembersRequest request) {
        ImportMembersParam param = new ImportMembersParam();
        param.setOrgId(request.getOrgId());
        param.setUserId(request.getUserId());
        param.setPrimaryKey(request.getPrimaryKey());
        param.setAttribute(request.getMemberTypeValue());
        param.setImportType(request.getImportTypeValue());
        param.setExistedUpdate(request.getExistedUpdate());
        param.setNullUpdate(request.getNullUpdate());
        param.setFileUrl(request.getFileUrl());
        return param;
    }

    /**
     * ImportRecordDTO to ImportRecord
     *
     * @param data
     * @return
     */
    private ImportRecord importRecordDTOToImport(ImportRecordDTO data) {
        ImportRecord.Builder builder = ImportRecord.newBuilder();
        builder.setPartialSuccess(data.getPartialSuccess());
        builder.setStatusValue(data.getStatus());
        builder.setId(data.getId());
        builder.setOrgId(data.getOrgId());
        builder.setFileName(data.getFileName());
        builder.setData(data.getData());
        builder.setMemberTypeValue(data.getMType());
        builder.setOpUserId(data.getUserId());
        return builder.build();
    }

    /**
     * request To GetImportRecordParam
     *
     * @param request
     * @return
     */
    private GetImportRecordParam requestToGetImportRecordParam(GetImportRecordRequest request) {
        GetImportRecordParam param = new GetImportRecordParam();
        param.setId(request.getId());
        param.setOrgId(request.getOrgId());
        return param;
    }

    /**
     * request To ListImportDetailsParam
     *
     * @param request
     * @return
     */
    private ListImportDetailsParam requestToListImportDetailsParam(ListImportDetailsRequest request) {
        ListImportDetailsParam param = new ListImportDetailsParam();
        param.setId(request.getId());

        PageParam pageParam = new PageParam();
        pageParam.setPage(request.getPage().getPage());
        pageParam.setSize(request.getPage().getSize());
        param.setPageParam(pageParam);
        return param;
    }

    /**
     * data to ImportFailureDetail
     *
     * @param data
     * @return
     */
    private List<ImportFailureDetail> dataToImportFailureDetail(List data) {
        List<ImportFailureDetail> details = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(data)) {
            data.forEach(d -> {
                ImportFailureDetail.Builder builder = ImportFailureDetail.newBuilder();
                ImportRecordDetailDTO dto = (ImportRecordDetailDTO) d;
                // 错误行数
                builder.setLine(dto.getLine());
                // 错误信息
                builder.setDesc(dto.getDesc());
                details.add(builder.build());
            });
        }
        return details;

    }

    /**
     * request To GetImportProgressParam
     *
     * @param request
     * @return
     */
    private GetImportProgressParam requestToGetImportProgressParam(GetImportProgressRequest request) {
        GetImportProgressParam param = new GetImportProgressParam();
        // 记录id
        param.setId(request.getId());
        // 组织id
        param.setOrgId(request.getOrgId());
        // 联系人类型
        param.setAttribute(request.getMemberTypeValue());
        return param;
    }

    /**
     * data to ImportRecord
     *
     * @param data
     * @return
     */
    private List<ImportRecord> dataToRecords(List data) {
        List<ImportRecord> importRecords = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(data)) {
            data.forEach(d -> {
                ImportRecord.Builder builder = ImportRecord.newBuilder();
                ImportRecordDTO importRecordDTO = (ImportRecordDTO) d;
                // 文件名
                builder.setFileName(importRecordDTO.getFileName());
                // id
                builder.setId(importRecordDTO.getId());
                // 状态
                builder.setStatusValue(importRecordDTO.getStatus());
                // 是否完全导入
                builder.setPartialSuccess(importRecordDTO.getPartialSuccess());
                // 时间
                BaseTime.Builder baseModelBuilder = BaseTime.newBuilder();
                baseModelBuilder.setCreateTime(GRpcUtil.getTimestamp(importRecordDTO.getCreateTime()));
                builder.setBase(baseModelBuilder.build());
                importRecords.add(builder.build());
            });
        }
        return importRecords;
    }

    /**
     * request To ListImportRecordsParam
     *
     * @param request
     * @return
     */
    private ListImportRecordsParam requestToListImportRecordsParam(ListImportRecordsRequest request) {
        ListImportRecordsParam param = new ListImportRecordsParam();
        param.setAttribute(request.getMemberTypeValue());
        param.setOrgId(request.getOrgId());

        PageParam pageParam = new PageParam();
        pageParam.setPage(request.getPage().getPage());
        pageParam.setSize(request.getPage().getSize());
        param.setPageParam(pageParam);

        List<SortParam> sortParamList = new ArrayList<>();
        List<Sort> sortByList = request.getSortByList();
        if (CollectionUtil.isNotEmpty(sortByList)) {
            sortByList.forEach(sort -> {
                SortParam sortParam = new SortParam();
                sortParam.setProperty(sort.getProperty());
                sortParam.setDirection(sort.getDirectionValue());
                sortParamList.add(sortParam);
            });
        }
        return param;
    }

    /**
     * request To CheckImportParam
     *
     * @param request
     * @return
     */
    private CheckImportParam requestToCheckImportParam(CheckImportRequest request) {
        CheckImportParam param = new CheckImportParam();
        // 组织id
        param.setOrgId(request.getOrgId());
        // 联系人类型
        param.setAttribute(request.getMemberTypeValue());
        return param;
    }

    /**
     * request To DownLoadTemplateParam
     *
     * @param request
     * @return
     */
    private DownLoadTemplateParam requestToDownLoadTemplateParam(DownLoadTemplateRequest request) {
        DownLoadTemplateParam param = new DownLoadTemplateParam();
        // 组织id
        param.setOrgId(request.getOrgId());
        // 模板名称
        param.setTemplateName(request.getTemplateName());
        return param;
    }
}
